﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Xml;
using WMPLib;

namespace EngineeringExamLearnAndTest
{
    public partial class Form1 : Form
    {
        private Question[] questionArray = new Question[500];
        private SessionTest session;
        private int iterQuest;
        private bool firstAnswer;
        private bool incorrectAnswer;

        public Form1()
        {
            InitializeComponent();
            session = new SessionTest();
            iterQuest = 0;
            firstAnswer = true;
            incorrectAnswer = false;

            //load questions
            if (File.Exists("Questions.xml"))
            {
                InitializeQuestions("Questions.xml");
            }
            else
            {
                InitializeQuestionFromFile();
            }

            //InitializeConfiguration();
            InitializeConfiguration();
        }

        public class Question
        {
            public Question()
            {
                Range = 0;
            }
            public int No;
            public string Quest;
            public string AnswerA;
            public string AnswerB;
            public string AnswerC;
            public string CorrectAnswer;
            public int Range;
        }

        private class SessionTest
        {
            public SessionTest()
            {
                lastQestion = 0;
                hardQuest = new List<int>();
                effect = 0.0;
                correct = 0;
                incorrect = 0;
                sessionQuestArray = new List<Question>();
            }
            public int lastQestion; //index
            public List<int> hardQuest; //indexes of hard questions
            public double effect;
            public int correct;
            public int incorrect;
            public List<Question> sessionQuestArray;

        }

        private void InitializeQuestions(string path)
        {
            XmlReader reader = new XmlTextReader(path);

            int iter = 0;
            while (reader.ReadToFollowing("QuestionObject"))
            {
                questionArray[iter] = new Question();

                reader.ReadToFollowing("QuestionID");
                questionArray[iter].No = Int16.Parse(reader.ReadString());

                reader.ReadToFollowing("Question");
                questionArray[iter].Quest = reader.ReadString();

                reader.ReadToFollowing("AnswerA");
                questionArray[iter].AnswerA = reader.ReadString();

                reader.ReadToFollowing("AnswerB");
                questionArray[iter].AnswerB = reader.ReadString();

                reader.ReadToFollowing("AnswerC");
                questionArray[iter].AnswerC = reader.ReadString();

                reader.ReadToFollowing("CorrectAnswer");
                questionArray[iter].CorrectAnswer = reader.ReadString();

                iter++;
            }
        }

        private void InitializeQuestionFromFile()
        {
            string filename = "";
            string path = "";
            OpenFileDialog ofd = new OpenFileDialog();

            ofd.InitialDirectory = "c:\\";
            ofd.Filter = "xml files (*.xml)|*.xml|All files (*.*)|*.*";
            ofd.FilterIndex = 2;
            ofd.RestoreDirectory = true;

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                filename = System.IO.Path.GetFileName(ofd.FileName);
                path = System.IO.Path.GetDirectoryName(ofd.FileName);
                InitializeQuestions(path + "/" + filename);
            }
        }

        private void InitializeSession()
        {
            if (cboMode.SelectedIndex == 0) //Nauka
            {
                if (chkLast.Checked == true)
                {
                    for (int iter = session.lastQestion; iter < 500; iter++)
                    {
                        if (chkHard.Checked)
                        {
                            if (session.hardQuest.Contains(iter))
                            {
                                session.sessionQuestArray.Add(questionArray[iter]);
                            }
                        }
                        else
                        {
                            session.sessionQuestArray.Add(questionArray[iter]);
                        }
                    }
                }
                else
                {
                    for (int iter = 0; iter < 500; iter++)
                    {
                        if (chkHard.Checked)
                        {
                            if (session.hardQuest.Contains(iter))
                            {
                                session.sessionQuestArray.Add(questionArray[iter]);
                            }
                        }
                        else
                        {
                            session.sessionQuestArray.Add(questionArray[iter]);
                        }
                    }
                }
            }
            else if (cboMode.SelectedIndex == 1) //Test
            {
                //Random Questions
                Random rnd = new Random();
                Question[] MyRandomArray = questionArray.OrderBy(x => rnd.Next()).ToArray();
                for (int i = 0; i < numQuest.Value; i++) session.sessionQuestArray.Add(MyRandomArray[i]);
            }

            //RANDOMIZE QUESTIONS
            if (chkRand.Checked == true){ 
                Random rnd = new Random();
                Question[] MyRandomArray = questionArray.ToArray<Question>().OrderBy(x => rnd.Next()).ToArray();
                session.sessionQuestArray.Clear();
                for (int i = 0; i < MyRandomArray.Length; i++) session.sessionQuestArray.Add(MyRandomArray[i]);
            }
        }

        private void InitializeConfiguration()
        {
            if (File.Exists("Config.xml"))
            {
                XmlReader reader = new XmlTextReader("Config.xml");

                reader.ReadToFollowing("LastQuestion");
                session.lastQestion = Int16.Parse(reader.ReadString());

                reader.ReadToFollowing("HardCheckBox");
                string value = reader.ReadString();
                if (value.ToLower() == "true") chkHard.Checked = true;
                else chkHard.Checked = false;

                reader.ReadToFollowing("LastCheckBox");
                value = reader.ReadString();
                if (value.ToLower() == "true") chkLast.Checked = true;
                else chkLast.Checked = false;

                reader.ReadToFollowing("RandCheckBox");
                value = reader.ReadString();
                if (value.ToLower() == "true") chkRand.Checked = true;
                else chkRand.Checked = false;

                reader.ReadToFollowing("BackCheckBox");
                value = reader.ReadString();
                if (value.ToLower() == "true") chkBack.Checked = true;
                else chkBack.Checked = false;

                reader.ReadToFollowing("SoundCheckBox");
                value = reader.ReadString();
                if (value.ToLower() == "true") chkSound.Checked = true;
                else chkSound.Checked = false;

                reader.ReadToFollowing("Mode");
                value = reader.ReadString();
                if (value == "Nauka") cboMode.SelectedIndex = 0;
                else cboMode.SelectedIndex = 1;

                reader.ReadToFollowing("RangeQuestions");
                string sHardQuest = reader.ReadString();
                string[] aHardQuest = sHardQuest.Split(new string[] { "|" }, StringSplitOptions.None);
                for (int i = 0; i < 500; i++)
                {
                    questionArray[i].Range = Int16.Parse(aHardQuest[i]);
                    if (Int16.Parse(aHardQuest[i]) < (int)numHard.Value) session.hardQuest.Add(i);
                }

                reader.Close();
            }
            else
            {
                if (MessageBox.Show("Can't load configuration file!", "Warning", MessageBoxButtons.OK) == System.Windows.Forms.DialogResult.OK)
                {
                    Application.Exit();
                }
            }
        }

        private void NextQuestion()
        {
            if (session.sessionQuestArray.Count == 0 || session.sessionQuestArray.Count == iterQuest)
            {
                btnStart.Enabled = false;
                btnFinish.Enabled = true;
                btnNext.Enabled = false;
                btnPrev.Enabled = false;

                return;
            }
            lblQuest.Text = session.sessionQuestArray[iterQuest].Quest;
            Random rnd = new Random();
            string[] questArray = { session.sessionQuestArray[iterQuest].AnswerA, session.sessionQuestArray[iterQuest].AnswerB, session.sessionQuestArray[iterQuest].AnswerC };
            string[] randQuestArray = questArray.OrderBy(x => rnd.Next()).ToArray();
            lblAnswerA.Text = randQuestArray[0];
            lblAnswerB.Text = randQuestArray[1];
            lblAnswerC.Text = randQuestArray[2];
        }

        private void cboMode_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cboMode.SelectedIndex == 0)
            {
                numQuest.Enabled = false;
                chkLast.Enabled = true;
                chkHard.Enabled = true;
                chkRand.Enabled = true;
                chkBack.Enabled = true;
            }
            else if (cboMode.SelectedIndex == 1)
            {
                numQuest.Enabled = true;
                chkLast.Enabled = false;
                chkHard.Enabled = false;
                chkRand.Enabled = false;
                chkBack.Enabled = false;
            }
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            btnFinish.Enabled = true;
            btnNext.Enabled = true;
            btnPrev.Enabled = true;

            session.correct = 0;
            session.incorrect = 0;
            session.effect = 0.0;
            lblCorrect.Text = "0";
            lblIncorrect.Text = "0";
            lblEffect.Text = "0";

            iterQuest = 0;

            if (chkLast.Checked) pgrStatus.Value = session.lastQestion;
            else pgrStatus.Value = 0;

            if (cboMode.SelectedIndex == 0) pgrStatus.Maximum = 500;
            else pgrStatus.Maximum = (int)numQuest.Value;

            //Initialize session with question
            InitializeSession();

            NextQuestion();

            lblState.Text = iterQuest.ToString() + "/" + session.sessionQuestArray.Count.ToString();
            btnStart.Enabled = false;
        }

        private void lblAnswerA_MouseHover(object sender, EventArgs e)
        {
            Cursor = Cursors.Hand;
        }

        private void lblAnswerA_MouseLeave(object sender, EventArgs e)
        {
            Cursor = Cursors.Default;
        }

        private void lblAnswerB_MouseHover(object sender, EventArgs e)
        {
            Cursor = Cursors.Hand;
        }

        private void lblAnswerB_MouseLeave(object sender, EventArgs e)
        {
            Cursor = Cursors.Default;
        }

        private void lblAnswerC_MouseHover(object sender, EventArgs e)
        {
            Cursor = Cursors.Hand;
        }

        private void lblAnswerC_MouseLeave(object sender, EventArgs e)
        {
            Cursor = Cursors.Default;
        }

        private void lblAnswerA_Click(object sender, EventArgs e)
        {
            if (session.sessionQuestArray[iterQuest].CorrectAnswer.ToLower() == "a")
            {
                CompareAnswersIfCorrect(lblAnswerA.Text, session.sessionQuestArray[iterQuest].AnswerA, lblAnswerA);
            }
            else if (session.sessionQuestArray[iterQuest].CorrectAnswer.ToLower() == "b")
            {
                CompareAnswersIfCorrect(lblAnswerA.Text, session.sessionQuestArray[iterQuest].AnswerB, lblAnswerA);
            }
            else if (session.sessionQuestArray[iterQuest].CorrectAnswer.ToLower() == "c")
            {
                CompareAnswersIfCorrect(lblAnswerA.Text, session.sessionQuestArray[iterQuest].AnswerC, lblAnswerA);
            }

            btnNext.Enabled = true;
            btnPrev.Enabled = true;
            btnNext.Focus();
        }

        private void lblAnswerB_Click(object sender, EventArgs e)
        {
            if (session.sessionQuestArray[iterQuest].CorrectAnswer.ToLower() == "a")
            {
                CompareAnswersIfCorrect(lblAnswerB.Text, session.sessionQuestArray[iterQuest].AnswerA, lblAnswerB);
            }
            else if (session.sessionQuestArray[iterQuest].CorrectAnswer.ToLower() == "b")
            {
                CompareAnswersIfCorrect(lblAnswerB.Text, session.sessionQuestArray[iterQuest].AnswerB, lblAnswerB);
            }
            else if (session.sessionQuestArray[iterQuest].CorrectAnswer.ToLower() == "c")
            {
                CompareAnswersIfCorrect(lblAnswerB.Text, session.sessionQuestArray[iterQuest].AnswerC, lblAnswerB);
            }

            btnNext.Enabled = true;
            btnPrev.Enabled = true;
            btnNext.Focus();
        }

        private void lblAnswerC_Click(object sender, EventArgs e)
        {
            if (session.sessionQuestArray[iterQuest].CorrectAnswer.ToLower() == "a")
            {
                CompareAnswersIfCorrect(lblAnswerC.Text, session.sessionQuestArray[iterQuest].AnswerA, lblAnswerC);
            }
            else if (session.sessionQuestArray[iterQuest].CorrectAnswer.ToLower() == "b")
            {
                CompareAnswersIfCorrect(lblAnswerC.Text, session.sessionQuestArray[iterQuest].AnswerB, lblAnswerC);
            }
            else if (session.sessionQuestArray[iterQuest].CorrectAnswer.ToLower() == "c")
            {
                CompareAnswersIfCorrect(lblAnswerC.Text, session.sessionQuestArray[iterQuest].AnswerC, lblAnswerC);
            }

            btnNext.Enabled = true;
            btnPrev.Enabled = true;
            btnNext.Focus();
        }

        private void CompareAnswersIfCorrect(string userAnswer, string correctAnswer, Label oLabel)
        {
            if (cboMode.SelectedIndex == 0)
            {
                if (userAnswer == correctAnswer)    //CORRECT ANSWER
                {
                    pnlResult.BackColor = Color.OliveDrab;
                    lblResult.Text = "Dobrze!";
                    pnlResult.Visible = true;
                    lblResult.Visible = true;
                    oLabel.BackColor = Color.OliveDrab;
                    if (firstAnswer)
                    {
                        session.correct++;
                        firstAnswer = false;
                    }
                    session.effect = (double)session.correct / (double)session.sessionQuestArray.Count;
                    lblCorrect.Text = session.correct.ToString();
                    lblEffect.Text = (Math.Round(session.effect, 2) * 100).ToString() + " %";

                    questionArray[session.sessionQuestArray[iterQuest].No - 1].Range++;

                    if (chkSound.Checked)
                    {
                        WindowsMediaPlayer wmp = new WindowsMediaPlayer();
                        wmp.URL = "CorrectAnswer.mp3";
                        wmp.controls.play();
                    }
                }
                else    //INCORRECT ANSWER
                {
                    pnlResult.BackColor = Color.Red;
                    lblResult.Text = "Źle!";
                    pnlResult.Visible = true;
                    lblResult.Visible = true;
                    oLabel.BackColor = Color.Red;
                    if (firstAnswer)
                    {
                        session.incorrect++;
                        firstAnswer = false;
                        incorrectAnswer = true;
                    }

                    lblIncorrect.Text = session.incorrect.ToString();

                    questionArray[session.sessionQuestArray[iterQuest].No - 1].Range--;

                    if (chkSound.Checked)
                    {
                        WindowsMediaPlayer wmp = new WindowsMediaPlayer();
                        wmp.URL = "WrongAnswer.mp3";
                        wmp.controls.play();
                    }
                }
            }
            else if (cboMode.SelectedIndex == 1)
            {
                //TODO
                //ADD test verification
            }
        }

        private void btnNext_Click(object sender, EventArgs e)
        {
            Next();
        }

        private void Next()
        {
            iterQuest++;
            pgrStatus.Value = iterQuest;
            firstAnswer = true;
            lblState.Text = iterQuest.ToString() + "/" + session.sessionQuestArray.Count.ToString();
            lblAnswerA.BackColor = Color.Cornsilk;
            lblAnswerB.BackColor = Color.Cornsilk;
            lblAnswerC.BackColor = Color.Cornsilk;

            if (iterQuest == session.sessionQuestArray.Count)   //Finish
            {
                lblQuest.Text = "Twój wynik to:";
                lblAnswerA.Text = "Poprawne odpowiedzi:\t" + session.correct.ToString();
                lblAnswerB.Text = "Niepoprawne odpowiedzi:\t" + session.incorrect.ToString();
                lblAnswerC.Text = "Procent poprawnych odpowiedzi:\t" + session.incorrect.ToString();
            }
            else
            {

                if (incorrectAnswer == true && chkBack.Checked == true)
                {
                    if ((iterQuest - 10) < 0)
                    {
                        iterQuest = 0;
                        incorrectAnswer = false;
                    }
                    else
                    {
                        iterQuest = iterQuest - 10;
                        incorrectAnswer = false;
                    }
                    lblState.Text = iterQuest.ToString() + "/" + session.sessionQuestArray.Count.ToString();
                }

                NextQuestion();

                pnlResult.Visible = false;
                lblResult.Visible = false;

                btnNext.Enabled = false;
                //btnPrev.Enabled = false;
            }
        }

        private void btnPrev_Click(object sender, EventArgs e)
        {
            iterQuest--;
            NextQuestion();
            pnlResult.Visible = false;
            lblResult.Visible = false;

            btnNext.Enabled = false;
            //btnPrev.Enabled = false;
        }

        private void btnFinish_Click(object sender, EventArgs e)
        {
            btnStart.Enabled = true;
            btnNext.Enabled = false;
            btnPrev.Enabled = false;
            lblState.Text = "0/0";
            lblAnswerA.BackColor = Color.Cornsilk;
            lblAnswerB.BackColor = Color.Cornsilk;
            lblAnswerC.BackColor = Color.Cornsilk;

            if (MessageBox.Show("Zapisać plik konfiguracyjny?", "Plik konfiguracyjny", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
            {
                SaveConfig();
            }
        }

        private void SaveConfig()
        {
            if (File.Exists("Config.xml")) File.Delete("Config.txt");

            XmlTextWriter writer = new XmlTextWriter("Config.xml", System.Text.Encoding.UTF8);

            writer.WriteStartDocument();
            writer.WriteWhitespace("\n");
            //Write the root element
            writer.WriteStartElement("Configuration");
            writer.WriteWhitespace("\n\t");

            //Write sub-elements
            writer.WriteElementString("LastQuestion", (500 - session.sessionQuestArray.Count + iterQuest).ToString());
            writer.WriteWhitespace("\n\t");
            writer.WriteElementString("HardCheckBox", chkHard.Checked.ToString());
            writer.WriteWhitespace("\n\t");
            writer.WriteElementString("LastCheckBox", chkLast.Checked.ToString());
            writer.WriteWhitespace("\n\t");
            writer.WriteElementString("RandCheckBox", chkRand.Checked.ToString());
            writer.WriteWhitespace("\n\t");
            writer.WriteElementString("BackCheckBox", chkBack.Checked.ToString());
            writer.WriteWhitespace("\n\t");
            writer.WriteElementString("SoundCheckBox", chkSound.Checked.ToString());
            writer.WriteWhitespace("\n\t");
            writer.WriteElementString("Mode", cboMode.SelectedItem.ToString());
            writer.WriteWhitespace("\n\t");
            writer.WriteElementString("RangeQuestions", GenerateRangeQuest());
            writer.WriteWhitespace("\n");

            // end the root element
            writer.WriteEndElement();
            //Write the XML to file and close the writer
            writer.Close();
        }

        private string GenerateRangeQuest()
        {
            string[] tab = new string[500];

            for (int i = 0; i < 500; i++)
            {
                tab[i] = questionArray[i].Range.ToString();
            }
            return string.Join("|", tab);
        }

        private void zapiszKonfiguracjęToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SaveConfig();
        }

        private void chkHard_CheckedChanged(object sender, EventArgs e)
        {
            if (chkHard.Checked == true) numHard.Enabled = true;
            else numHard.Enabled = false;
        }
    }
}
